AWS Config の料金がなぜこんなに高い? Amazon Athena でどのリソースが Config の記録対象になっているか調べてみた
うわっ… Config の料金、高すぎ…?
コンバンハ、千葉(幸)です。
AWS Config では、記録された設定項目(configuration item recorded)ごとに 0.003 USD かかります。(2021年9月時点の東京リージョンの場合。)
リソースの新規作成や設定変更、削除が頻繁に行われる環境では意図せず料金が膨らむ場合もあります。
▲ 過去に見たことがある Config の料金が爆発した例
AWS Config のダッシュボードではその時点で記録対象となっているリソースの数を確認できますが、既存のリソースに設定変更が多く発生している・あるいは作成/削除が繰り返されている場合には、設定項目数の内訳を確認するのは難しいです。
そのようなケースにおいて、 S3 バケットに出力された Config のスナップショットファイルを Athena で分析することで対象を特定できるため、手順を確認してみることにしました。
ほぼほぼ以下の内容をなぞったものになっています。
今回の登場人物
この方々です。
# | 登場人物 | 説明 |
---|---|---|
1 | Config レコーダー | どのリソースを記録するかの定義をしている |
2 | Config 配信チャネル | どの S3 バケットに出力するかの定義をしている |
3 | Config 出力先 S3 バケット | #2 から出力された履歴、スナップショットが格納されている |
4 | Athena | #3 の中身をクエリしよう! |
5 | Athena 出力先 S3 バケット | #4 の結果が格納される |
わたしの検証環境で試していきます。
Config の設定確認
AWS Config 配信チャネルで、出力先の S3 バケットがどこであるか確認しましょう。
普段独立したリソースとして意識する機会は少ないと思いますが、マネジメントコンソールで以下から確認できる部分は配信チャネルの設定を表しています。
S3 バケットに格納されたオブジェクトの URI の例は以下です。
s3://バケット名/AWSLogs/アカウント番号/Config/ap-northeast-1/2021/9/24/ConfigSnapshot/ファイル名.json.gz
ちょっとした気づきですが、yyyy/mm/dd
形式になっていません。2021/09/24
のように月や日を 2 桁に揃えてくれるわけでなく、元の数字が 1 桁のままであればそのまま 1 桁です。
Athena のクエリ結果の出力先 S3 バケットの作成
今回は初めて Athena を利用するケースを想定し、順番に進めていきます。
後ほど出力先設定が必要となるので、あらかじめ適当なバケットを用意しておきましょう。Athena を利用するリージョンと同じリージョンに用意してください。
クエリを実行する AWS エンティティ( マネジメントコンソールを操作する IAM ユーザーや IAM ロール)が S3 にアクセスできれば良いので、 Athena 特有のバケットポリシーなどは必要ありません。
既存のものを使用するのであればそれでも大丈夫です。
Athena のセットアップ
Athena のサービス画面に移動します。「クエリエディタ」という画面で操作することになるので、進みます。
デフォルトで用意されているワークグループprimary
に遷移します。ワークグループは、Athena における一番でかい箱だと思ってください。
最初のクエリを実行する前に、Amazon S3 でクエリ結果の場所を設定する必要があります。
という注意書きがあります。設定を進めないとクエリが実行できないため、設定画面に移ります。
ワークグループprimary
としての、クエリ結果の出力先 S3 バケットの設定をします。
先ほど用意した出力用バケットを選択して保存すればOKです。
これで最初の準備ができました。
Athena テーブルの作成
テーブルを作成していきます。クエリエディタに以下をペーストし実行してください。なお、ハイライト部のロケーションは環境に合わせて修正してください。
CREATE EXTERNAL TABLE awsconfig ( fileversion string, configSnapshotId string, configurationitems ARRAY < STRUCT < configurationItemVersion : STRING, configurationItemCaptureTime : STRING, configurationStateId : BIGINT, awsAccountId : STRING, configurationItemStatus : STRING, resourceType : STRING, resourceId : STRING, resourceName : STRING, ARN : STRING, awsRegion : STRING, availabilityZone : STRING, configurationStateMd5Hash : STRING, resourceCreationTime : STRING > > ) ROW FORMAT SERDE 'org.apache.hive.hcatalog.data.JsonSerDe' LOCATION 's3://バケット名/AWSLogs/アカウント番号/Config/リージョン/2021/';
↑ハイライト部には初めに確認した Config の出力先バケットとプレフィックスを指定します。わたしは2021
というプレフィックスまで指定しましたが、より広くしても狭くしても問題ありません。
実行すると、先頭行で指定しているawsconfig
という名称でテーブルが作成されました。特に指定をしていないためdefault
というデータベースの中にテーブルが作成されています。
以降のクエリではdefault.awsconfig
という形でデータベースおよびテーブル名を指定しますが、別の名称で作成された場合には適宜読み替えてください。
Athena のスキャン対象のサイズはどのくらい?
Athena の料金はクエリ実行時にスキャンしたデータサイズによって変動します。東京リージョンでは スキャンされたデータ 1 TB あたり 5.00 USD です。
参照系のクエリ実行時には、テーブル作成時に指定した S3 バケットのプレフィックス配下をすべてスキャンすることになります。
わたしの環境でのサイズを確認すると、およそ 28.2 MiB でした。以降のクエリ実行では、都度このサイズをスキャンすることになります。
% aws s3 ls バケット名/AWSLogs/アカウント番号/Config/ap-northeast-1/2021/ --recursive --summarize --human-readable > /tmp/hoge.txt && tail -n 2 /tmp/hoge.txt Total Objects: 1770 Total Size: 28.2 MiB
そこまでサイズは大きくないので問題なさそうです。指定するプレフィックスにより変動するので、意識するようにしましょう。
今回は使用しませんが、スキャン対象を限定するためのパーティションという考え方もあります。覚えておきましょう。
Athena でのクエリの実行
いくつかのパターンで実行します。
日別の設定項目数を確認する
クエリの例は以下です。ハイライト部の期間は環境に合わせて修正してください。
SELECT result.configurationitemcapturetime, count(result.configurationitemcapturetime) AS NumberOfChanges FROM (SELECT regexp_replace(configurationItem.configurationItemCaptureTime, '(.+)(T.+)', '$1') AS configurationitemcapturetime FROM default.awsconfig CROSS JOIN UNNEST(configurationitems) AS t(configurationItem) WHERE "$path" LIKE '%ConfigHistory%' AND configurationItem.configurationItemCaptureTime >= '2021-07-01T%' AND configurationItem.configurationItemCaptureTime <= '2021-08-28T%') result GROUP BY result.configurationitemcapturetime ORDER BY result.configurationitemcapturetime
期間内の日ごとに、Config の設定項目( configuration item )数を確認できます。
リソースごとの設定項目数を降順にソートする
クエリの例は以下です。
SELECT configurationItem.resourceType, configurationItem.resourceId, COUNT(configurationItem.resourceId) AS NumberOfChanges FROM default.awsconfig CROSS JOIN UNNEST(configurationitems) AS t(configurationItem) WHERE "$path" LIKE '%ConfigHistory%' AND configurationItem.configurationItemCaptureTime >= '2021-08-01T%' AND configurationItem.configurationItemCaptureTime <= '2021-08-28T%' GROUP BY configurationItem.resourceType, configurationItem.resourceId ORDER BY NumberOfChanges DESC
リソース ID ごとに、Config の設定項目数を確認できます。
リソースタイプごとの設定項目数を降順にソートする
クエリの例は以下です。
SELECT configurationItem.resourceType, COUNT(configurationItem.resourceType) AS NumberOfChanges FROM default.awsconfig CROSS JOIN UNNEST(configurationitems) AS t(configurationItem) WHERE "$path" LIKE '%ConfigHistory%' AND configurationItem.configurationItemCaptureTime >= '2021-04-01T%' AND configurationItem.configurationItemCaptureTime <= '2021-04-30T%' GROUP BY configurationItem.resourceType ORDER BY NumberOfChanges DESC
特定のリソースで設定項目が多ければ先ほどのクエリで確認できますが、「一つ一つのリソースでは少ないがリソース数自体が多い」というケースにはマッチしません。
リソースタイプの単位で確認したい時にはこちらのクエリを使用してください。
( IAM ロールだけで 912 の設定項目……どういう時にこんなことになるんでしょうね。ちっとも分かりません。)
特定のリソースタイプに限定してクエリする
クエリ例は以下です。 「リソースごとの設定項目数を降順にソートする」をベースに、WHERE 句 に条件を追加しています。
SELECT configurationItem.resourceType, configurationItem.resourceId, COUNT(configurationItem.resourceId) AS NumberOfChanges FROM default.awsconfig CROSS JOIN UNNEST(configurationitems) AS t(configurationItem) WHERE "$path" LIKE '%ConfigHistory%' AND configurationItem.configurationItemCaptureTime >= '2021-04-01T%' AND configurationItem.configurationItemCaptureTime <= '2021-04-30T%' AND configurationItem.resourceType = 'AWS::IAM::Role' GROUP BY configurationItem.resourceType, configurationItem.resourceId ORDER BY NumberOfChanges DESC
特定のリソースタイプだけに限定して、リソース ID ごとの設定項目数を確認できます。
( IAM ロールごとの設定項目数はほぼ 1 なので、IAM ロールが 900 個くらい増えた時期があったんですかね。なんでだろう。ちっとも分かりません。)
Config レコーダーで記録対象を変更する
ここまでのクエリで、お手元の環境では特定のリソースや特定のリソースタイプに設定項目が集中していることが確認できたのではないでしょうか。
ループ処理のように意図せず作成/削除が行われていた、といった原因であればリソース側の設定変更で回避できるかと思います。
とは言え、今後同じことが起こらないように記録対象から除外しておきたい、必要があって定常的に発生する処理なのでリソース側での設定変更はしたくない、ということもあるでしょう。その場合には Config レコーダーの設定を変更することで対応できます。
Config の「設定」から、記録するリソースタイプを選択できます。画像ではすべてのリソースを選択する設定となっています。
「特定のリソースタイプを記録する」に切り替えることによって、記録対象をコントロールできます。記録する対象を一つずつ選択していく方法もあれば、記録したくないリソースを除いていく方法もあります。
後者の場合、一度以下のようにすべての AWS リソースタイプを記録するようにして設定を保存してください。
再度設定を開き直すと以下のようにリソースタイプが全選択された状態となっているため、除外したいものを削除していってください。
Config による記録はなるべく多くのリソースタイプに対して有効になっていることが望ましいですが、コスト見合いで必要なもののみを選択する、というのも大事な視点です。
終わりに
Athena で AWS Config の記録された設定項目数の内訳を確認する手順を試してみました。
Athena をあまり使ったことがなかったのですが、サンプルが提供されていたのでそこまで迷わず試せました。きちんと対象を絞れば料金もそこまでかからなさそうであるため、これまで使ったことがない方は試してみてはいかがでしょうか。
AWS Confg の料金暴騰の原因特定にお役立てください。
以上、 チバユキ (@batchicchi) がお送りしました。